package com.crm.business.crm.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.crm.business.admin.service.AdminFileService;
import com.crm.business.admin.service.AdminService;
import com.crm.business.admin.service.IAdminDeptService;
import com.crm.business.crm.mapper.CrmCustomerMapper;
import com.crm.business.crm.mapper.CrmLeadsMapper;
import com.crm.business.crm.service.*;
import com.crm.business.servlet.BaseServiceImpl;
import com.crm.business.utils.ActionRecordUtil;
import com.crm.business.utils.UserCacheUtil;
import com.crm.business.utils.UserUtil;
import com.crm.common.admin.entity.PO.AdminDept;
import com.crm.common.crm.common.CrmModel;
import com.crm.common.crm.constant.CrmActivityEnum;
import com.crm.common.crm.constant.CrmBackLogEnum;
import com.crm.common.crm.constant.CrmCodeEnum;
import com.crm.common.crm.constant.CrmEnum;
import com.crm.common.crm.constant.FieldEnum;
import com.crm.common.crm.entity.BO.*;
import com.crm.common.crm.entity.PO.*;
import com.crm.common.crm.entity.VO.*;
import com.crm.common.ka.core.common.Const;
import com.crm.common.ka.core.common.Result;
import com.crm.common.ka.core.common.log.BehaviorEnum;
import com.crm.common.ka.core.entity.BasePage;
import com.crm.common.ka.core.exception.CrmException;
import com.crm.common.ka.core.feign.admin.entity.AdminMessageEnum;
import com.crm.common.ka.core.feign.crm.entity.CrmEventBO;
import com.crm.common.ka.core.feign.crm.entity.QueryEventCrmPageBO;
import com.crm.common.ka.core.redis.RedisImpl;
import com.crm.common.ka.core.servlet.upload.FileEntity;
import com.crm.common.utils.DateUtils;
import com.crm.common.utils.StringUtils;
import com.crm.common.utils.spring.SpringUtils;

import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.interceptor.TransactionAspectSupport;


/**
 * <p>
 * 线索表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-05-21
 */
@Service
@Slf4j
public class CrmLeadsServiceImpl extends BaseServiceImpl<CrmLeadsMapper, CrmLeads> implements ICrmLeadsService, CrmPageService {
    @Autowired
    private AdminService adminService;
    @Autowired
    private IAdminDeptService adminDeptService;
    @Autowired
    private ICrmFieldService crmFieldService;

    @Autowired
    private ICrmLeadsDataService crmLeadsDataService;

    @Autowired
    private ICrmLeadsUserStarService crmLeadsUserStarService;

    @Autowired
    private ICrmBackLogDealService crmBackLogDealService;

    @Autowired
    private ICrmActivityService crmActivityService;

    @Autowired
    private ICrmActionRecordService crmActionRecordService;

    @Autowired
    private ICrmCustomerService crmCustomerService;

    @Autowired
    private ICrmCustomerSettingService crmCustomerSettingService;

    @Autowired
    private ICrmCustomerDataService crmCustomerDataService;

    @Autowired
    private AdminFileService adminFileService;

    @Resource
    private CrmPageService customerService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ActionRecordUtil actionRecordUtil;

    @Autowired
    private RedisImpl redis;

    @Autowired
    private IBillCrmTrainingService crmTrainingService;


    /**
     * 大的搜索框的搜索字段
     *
     * @return fields
     */
    @Override
    public String[] appendSearch() {
        return new String[]{"leadsName", "telephone", "mobile", "wechat"};
    }

    @Override
    public CrmEnum getLabel() {
        return CrmEnum.LEADS;
    }

    /**
     * 查询所有字段
     *
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryDefaultField() {
        List<CrmModelFiledVO> filedList = crmFieldService.queryField(getLabel().getType());
        filedList.add(new CrmModelFiledVO("lastTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("lastContent", FieldEnum.TEXTAREA, 1));
        filedList.add(new CrmModelFiledVO("updateTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("createTime", FieldEnum.DATETIME, 1));
        filedList.add(new CrmModelFiledVO("ownerUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("createUserId", FieldEnum.USER, 1));
        filedList.add(new CrmModelFiledVO("ownerUserName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("teacherName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("createUserName", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("serialNumber", FieldEnum.TEXT, 1));
        filedList.add(new CrmModelFiledVO("teacherId", FieldEnum.USER, 1));
        return filedList;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public List<CrmModelFiledVO> queryField(Integer id) {
        CrmModel crmModel = queryById(id);
        List<CrmModelFiledVO> list = crmFieldService.queryField(crmModel);
        //新增线索页面  将 报课时间 和  加微信时间  唯一标识  数据来源 去掉   不做展示

//        list.removeIf(field -> field.getFieldName().equals("signClassTime"));
//        list.removeIf(field -> field.getFieldName().equals("addWechatTime"));
        list.removeIf(field -> field.getFieldName().equals("serialNumber"));
        list.removeIf(field -> field.getFieldName().equals("isTransform"));
        list.removeIf(field -> field.getFieldName().equals("vipDealStatus"));
        list.removeIf(field -> field.getFieldName().equals("vipDealTime"));
        list.removeIf(field -> field.getFieldName().equals("isRepetition"));
        return list;
    }

    @Override
    public BasePage<Map<String, Object>> queryListByInstrumentImpl(CrmSearchBO crmSearchBO) {
        BasePage<Map<String, Object>> basePage = queryListByInstrument(crmSearchBO);
        Long userId = UserUtil.getUserId();
        List<Integer> starIds = crmLeadsUserStarService.starList(userId);
        basePage.getList().forEach(map -> {
            map.put("star", starIds.contains((Integer) map.get("leadsId")) ? 1 : 0);
        });
        return basePage;
    }

    @Override
    public BasePage<Map<String, Object>> queryListByInstrumentImplNotLeads(CrmSearchBO crmSearchBO) {
        BasePage<Map<String, Object>> basePage = queryListByInstrumentNotLeads(crmSearchBO);
        Long userId = UserUtil.getUserId();
        List<Integer> starIds = crmLeadsUserStarService.starList(userId);
        basePage.getList().forEach(map -> {
            map.put("star", starIds.contains((Integer) map.get("leadsId")) ? 1 : 0);
        });
        return basePage;
    }

    /**
     * 分页查询
     *
     * @param search
     * @return
     */
    @Override
    public BasePage<Map<String, Object>> queryPageList(CrmSearchBO search) {
        BasePage<Map<String, Object>> basePage = queryList(search);
        Long userId = UserUtil.getUserId();
        List<Integer> starIds = crmLeadsUserStarService.starList(userId);
        List<AdminDept> deptList = adminDeptService.list();
        Map<Integer,AdminDept> deptMap =  deptList.stream().collect(Collectors.toMap(AdminDept::getDeptId, v -> v, (p1, p2) -> p1));
        basePage.getList().forEach(map -> {
            if (ObjectUtil.isNotEmpty(map.get("teacherId"))) {
                // 营销讲师名称回显
                Long teacherId = Long.valueOf(String.valueOf(map.get("teacherId")));
                if (ObjectUtil.isNotEmpty(teacherId)) {
                    String teacherName = UserCacheUtil.getUserName(teacherId);
                    map.put("teacherName", teacherName);
                }
            }

            // 负责人名称回显
            if (ObjectUtil.isNotEmpty(map.get("ownerUserId"))) {
                Long ownerUserId = Long.valueOf(String.valueOf(map.get("ownerUserId")));
                if (ObjectUtil.isNotEmpty(ownerUserId)) {
                    String ownerUserName = UserCacheUtil.getUserName(ownerUserId);
                    map.put("ownerUserName", ownerUserName);
                }
            }

            //创建人名称回显
            if (ObjectUtil.isNotEmpty(map.get("createUserId"))) {
                Long createUserId = Long.valueOf(String.valueOf(map.get("createUserId")));
                if (ObjectUtil.isNotEmpty(createUserId)) {
                    String createUserName = UserCacheUtil.getUserName(createUserId);
                    map.put("createUserName", createUserName);
                }
            }

            //线索负责人名称回显
            if (ObjectUtil.isNotEmpty(map.get("leadsUserId"))) {
                Long leadsUserId = Long.valueOf(String.valueOf(map.get("leadsUserId")));
                if (ObjectUtil.isNotEmpty(leadsUserId)) {
                    String leadsUserName = UserCacheUtil.getUserName(leadsUserId);
                    map.put("leadsUserName", leadsUserName);
                }
            }

            //负责人所在部门
            if (ObjectUtil.isNotEmpty(map.get("ownerDeptId"))) {
                Long ownerDeptId = Long.valueOf(String.valueOf(map.get("ownerDeptId")));
                if (ObjectUtil.isNotEmpty(ownerDeptId)) {
//                    String ownerDeptName = adminService.queryDeptName(Integer.valueOf(ownerDeptId.toString()));
                    map.put("ownerDeptName", StringUtils.EMPTY);
                    AdminDept dept = deptMap.get(ownerDeptId);
                    if(Optional.ofNullable(dept).isPresent()){
                        map.put("ownerDeptName", dept.getName());
                    }
                }
            }


            map.put("star", starIds.contains((Integer) map.get("leadsId")) ? 1 : 0);
        });
        return basePage;
    }

    /**
     * 查询字段配置
     *
     * @param id 主键ID
     * @return data
     */
    @Override
    public CrmModel queryById(Integer id) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(id, UserUtil.getUserId());
            String name = UserCacheUtil.getUserName((Long) crmModel.get("teacherId"));
            crmModel.put("teacherName", name);
            crmModel.setLabel(CrmEnum.LEADS.getType());
            crmModel.setOwnerUserName(UserCacheUtil.getUserName(crmModel.getOwnerUserId()));
            crmLeadsDataService.setDataByBatchId(crmModel);
            // 权限类型  1不可编辑不可查看 2可查看不可编辑 3可编辑可查看
            //查询 分配给角色和机构  权限为  1  的字段 或 小于  1的字段
            List<String> stringList = SpringUtils.getBean(ICrmRoleFieldService.class).queryNoAuthField(crmModel.getLabel());
            List<String> deptFieldList = SpringUtils.getBean(ICrmDeptFieldService.class).queryNoAuthField(crmModel.getLabel());
            stringList = stringList.stream().filter(field -> deptFieldList.contains(field)).collect(Collectors.toList());

            stringList = stringList.stream().distinct().collect(Collectors.toList());

            stringList.forEach(crmModel::remove);
        } else {
            crmModel = new CrmModel(CrmEnum.LEADS.getType());
        }
        return crmModel;
    }

    /**
     * 针对转化查询数据信息
     *
     * @param id
     * @return
     */
    public CrmModel queryByIdToTransfer(Integer id) {
        CrmModel crmModel;
        if (id != null) {
            crmModel = getBaseMapper().queryById(id, UserUtil.getUserId());
            crmModel.setLabel(CrmEnum.LEADS.getType());
            crmModel.setOwnerUserName(UserCacheUtil.getUserName(crmModel.getOwnerUserId()));
            crmLeadsDataService.setDataByBatchId(crmModel);
        } else {
            crmModel = new CrmModel(CrmEnum.LEADS.getType());
        }
        return crmModel;
    }


    /**
     * 保存或新增信息
     *
     * @param crmModel model
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(CrmModelSaveBO crmModel, boolean isExcel) {
        if (String.valueOf(crmModel.getEntity().get("ownerUserId")).split(",").length > 1) {
            throw new CrmException(CrmCodeEnum.CRM_LEADS_OWNER_USER_TOO_LONG);
        }

        CrmLeads crmLeads = BeanUtil.copyProperties(crmModel.getEntity(), CrmLeads.class);

        String batchId = StrUtil.isNotEmpty(crmLeads.getBatchId()) ? crmLeads.getBatchId() : IdUtil.simpleUUID();
        actionRecordUtil.updateRecord(crmModel.getField(), Dict.create().set("batchId", batchId).set("dataTableName", "bill_crm_leads_data"));
        if (CollectionUtil.isNotEmpty(crmModel.getField())) {
            CrmModel model = new CrmModel();
            //如果是修改 则先查询 线索数据
            if (StrUtil.isNotEmpty(crmLeads.getBatchId())) {
                model = getBaseMapper().queryById(crmLeads.getLeadsId(), UserUtil.getUserId());
                crmLeadsDataService.setDataByBatchId(model);
            }
        }

        if (StrUtil.isEmpty(crmLeads.getBatchId())) {
            LocalDate date = LocalDate.now();
            String dateStr = date.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            crmLeads.setSerialNumber(dateStr + "-" + UUID.randomUUID().toString().replace("-", "").substring(0, 8));
        }

        crmLeadsDataService.saveData(crmModel.getField(), batchId);
        if (StrUtil.isEmpty(crmLeads.getEmail())) {
            crmLeads.setEmail(null);
        }
        //修改下次联系时间,待办事项需要提醒,需要同步最后跟进时间
        if (crmLeads.getNextTime() != null) {
            crmLeads.setLastTime(DateUtil.date());
        }
        if (StringUtils.isEmpty(crmLeads.getIsRepetition())) {
            if (crmLeads.getLeadsId() != null) {
                CrmLeads tempLeads = BeanUtil.copyProperties(this.queryById(crmLeads.getLeadsId()), CrmLeads.class);
                if ("是".equals(tempLeads.getIsRepetition())) {
                    crmLeads.setIsRepetition("是");
                } else {
                    crmLeads.setIsRepetition("否");
                }
            } else {
                crmLeads.setIsRepetition("否");
            }
        }
        //验证电话格式
        if (StringUtils.isNotBlank(crmLeads.getTelephone())) {
            if (!(crmLeads.getTelephone().matches(Const.REG_EXP_MOBILE) || crmLeads.getTelephone().matches(Const.REG_EXP_TELEPHONE))) {
                throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
            }
        }
        boolean isUpdate = false;
        CrmLeads oldLeads = new CrmLeads();
        if (crmLeads.getLeadsId() != null) {
            isUpdate = true;
            CrmLeads leads = this.getById(crmLeads.getLeadsId());
            BeanUtils.copyProperties(leads, oldLeads);
            if (UserUtil.getUser().getRoles().indexOf(UserUtil.getSuperRole()) != -1) {
            } else {
                if (leads.getIsTransform() == 1) {
                    throw new CrmException(CrmCodeEnum.CRM_LEADS_EDIT_ISTRANSFER_ERROR);
                }
            }
            if (leads.getCustomerId() != null && leads.getCustomerId() != 0) {
            } else {
                crmLeads.setCustomerId(0);
            }
            crmLeads.setUpdateTime(DateUtil.date());

            actionRecordUtil.updateRecord(BeanUtil.beanToMap(getById(crmLeads.getLeadsId())), BeanUtil.beanToMap(crmLeads), CrmEnum.LEADS, crmLeads.getLeadsName(), crmLeads.getLeadsId());
            updateById(crmLeads);
            if (StringUtils.isNotBlank(crmLeads.getAddWechat()) && "否".equals(crmLeads.getAddWechat())) {
                crmLeadsMapper.updateAddWechatTimeIsNull(crmLeads.getLeadsId());
            }
            if (StringUtils.isNotBlank(crmLeads.getSignClass()) && "否".equals(crmLeads.getSignClass())) {
                crmLeadsMapper.updateSignClassTimeIsNull(crmLeads.getLeadsId());
            }
            //查询一次保存es,因为有些字段没有保存es会出现null
            crmLeads = getById(crmLeads.getLeadsId());
            crmBackLogDealService.deleteByType(crmLeads.getOwnerUserId(), CrmEnum.LEADS, CrmBackLogEnum.FOLLOW_LEADS, crmLeads.getLeadsId());
        } else {

            crmLeads.setCreateTime(DateUtil.date());
            crmLeads.setUpdateTime(DateUtil.date());
            crmLeads.setCreateUserId(UserUtil.getUserId());
            crmLeads.setIsTransform(0);
            if (!isExcel) {
                crmLeads.setFollowup(0);
            }
            crmLeads.setCreateUserId(UserUtil.getUserId());
            if (crmLeads.getOwnerUserId() == null) {
                crmLeads.setOwnerUserId(UserUtil.getUserId());
            }
            crmLeads.setBatchId(batchId);
            //设置新老数据字段值为新数据：有成：代表旧数据；涵品：代表新数据
            crmLeads.setVipDealStatus("未成交");
            save(crmLeads);
            actionRecordUtil.addRecord(crmLeads.getLeadsId(), CrmEnum.LEADS, crmLeads.getLeadsName());
        }
        crmModel.setEntity(BeanUtil.beanToMap(crmLeads));
        savePage(crmModel, crmLeads.getLeadsId(), isExcel);

        if (isUpdate) {
            if (!ObjectUtil.equal(oldLeads.getOwnerUserId(), crmLeads.getOwnerUserId())) {
                String ownerUserName = UserCacheUtil.getUserName(crmLeads.getOwnerUserId());

                if (oldLeads.getOwnerUserId() != null) {
                    addMessage(oldLeads.getCustomerName(), ownerUserName, oldLeads.getOwnerUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), crmLeads.getLeadsId());
                }

                if (crmLeads.getOwnerUserId() != null) {
                    addMessage(oldLeads.getCustomerName(), ownerUserName, crmLeads.getOwnerUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), crmLeads.getLeadsId());
                }
            }

            if (!ObjectUtil.equal(oldLeads.getLeadsUserId(), crmLeads.getLeadsUserId())) {
                String leadsUserName = UserCacheUtil.getUserName(crmLeads.getLeadsUserId());

                if (oldLeads.getLeadsUserId() != null) {
                    addMessage(oldLeads.getCustomerName(), leadsUserName, oldLeads.getLeadsUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), crmLeads.getLeadsId());
                }

                if (crmLeads.getLeadsUserId() != null) {
                    addMessage(oldLeads.getCustomerName(), leadsUserName, crmLeads.getLeadsUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), crmLeads.getLeadsId());
                }
            }

            if (!ObjectUtil.equal(oldLeads.getTeacherId(), crmLeads.getTeacherId())) {
                String teacherName = UserCacheUtil.getUserName(crmLeads.getTeacherId());

                if (oldLeads.getTeacherId() != null) {
                    addMessage(oldLeads.getCustomerName(), teacherName, oldLeads.getTeacherId(), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                }

                if (crmLeads.getTeacherId() != null) {
                    addMessage(oldLeads.getCustomerName(), teacherName, crmLeads.getTeacherId(), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                }
            }
        }
    }

    @Override
    public void setOtherField(Map<String, Object> map) {
        String ownerUserName = UserCacheUtil.getUserName((Long) map.get("ownerUserId"));
        map.put("ownerUserName", ownerUserName);
        String createUserName = UserCacheUtil.getUserName((Long) map.get("createUserId"));
        map.put("createUserName", createUserName);
        String teacherName = UserCacheUtil.getUserName((Long) map.get("teacherId"));
        map.put("teacherName", teacherName);
    }


    /**
     * 删除线索数据
     *
     * @param ids ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(List<Integer> ids) {
        LambdaQueryWrapper<CrmLeads> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CrmLeads::getBatchId);
        wrapper.in(CrmLeads::getLeadsId, ids);
        List<String> batchIdList = listObjs(wrapper, Object::toString);

        List<CrmLeads> crmLeadsList = baseMapper.queryByIds(ids);
        for (CrmLeads leads : crmLeadsList) {
            if (1 == leads.getIsTransform()) {
                //若已转化，则不允许删除
                throw new CrmException(CrmCodeEnum.CRM_LEADS_IS_TRANSFER);
            }
        }

        //删除跟进记录
        crmActivityService.deleteActivityRecord(CrmActivityEnum.LEADS, ids);
        //删除字段操作记录
        crmActionRecordService.deleteActionRecord(CrmEnum.LEADS, ids);
        //删除自定义字段
        crmLeadsDataService.deleteByBatchId(batchIdList);
        //todo 删除文件,暂不处理
        removeByIds(ids);
        //删除es数据
        deletePage(ids);
    }

    /**
     * 修改线索负责人
     *
     * @param leadsIds       线索id列表
     * @param newOwnerUserId 新销售负责人ID
     * @param newOwnerUserId 新线索负责人ID
     */
    @Override
    public void changeOwnerUser(List<Integer> leadsIds, Long newOwnerUserId, Long newLeadsUserId) {

        if (newOwnerUserId == null && newLeadsUserId == null) {
            throw new CrmException(CrmCodeEnum.CRM_LEADS_CHANGE_USER_IS_NULL);
        }

        Map<String, Object> map = new HashMap<>();
        String ownerUserName = newOwnerUserId == null ? "" : UserCacheUtil.getUserName(newOwnerUserId);
        String leadsUserName = newLeadsUserId == null ? "" : UserCacheUtil.getUserName(newLeadsUserId);

        // 根据转化勾选的数据Id获取到所有数据信息
        List<CrmLeads> leadsList = this.crmLeadsMapper.queryDataCountByLeadsId(leadsIds);

        LambdaUpdateWrapper<CrmLeads> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CrmLeads::getLeadsId, leadsIds);
        if (newOwnerUserId != null) {
            wrapper.set(CrmLeads::getOwnerUserId, newOwnerUserId);
        }
        if (newLeadsUserId != null) {
            wrapper.set(CrmLeads::getLeadsUserId, newLeadsUserId);
        }
        wrapper.set(CrmLeads::getFollowup, 0);
        wrapper.set(CrmLeads::getIsReceive, 1);
        update(wrapper);
        for (Integer leadsId : leadsIds) {
            actionRecordUtil.conversionRecordAdd(leadsId, CrmEnum.LEADS, newOwnerUserId, newLeadsUserId, getById(leadsId).getLeadsName());
//            actionRecordUtil.addConversionRecord(leadsId,CrmEnum.LEADS,newOwnerUserId,getById(leadsId).getLeadsName());
        }
        //修改es
        if (newOwnerUserId != null) {
            map.put("ownerUserId", newOwnerUserId);
            map.put("ownerUserName", ownerUserName);
        }
        if (newLeadsUserId != null) {
            map.put("leadsUserId", newLeadsUserId);
            map.put("leadsUserName", leadsUserName);
        }
        map.put("followup", 0);
        map.put("isReceive", 1);
        updateField(map, leadsIds);

        // 当前登录人等于老负责人 只给新负责人发 其他 给老负责人与新负责人都发
        for (CrmLeads leads : leadsList) {
            if(newOwnerUserId != null){
                if(!ObjectUtil.equal(leads.getOwnerUserId(),newOwnerUserId)){
                    if ((!UserUtil.getUserId().equals(leads.getOwnerUserId())) && leads.getOwnerUserId() != null) {
                        addMessage(leads.getCustomerName(), ownerUserName, leads.getOwnerUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), leads.getLeadsId());
                    }

                    if ((!UserUtil.getUserId().equals(newOwnerUserId)) && newOwnerUserId != null) {
                        addMessage(leads.getCustomerName(), ownerUserName, newOwnerUserId, AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), leads.getLeadsId());
                    }
                }
            }

            if(newLeadsUserId != null){
                if(!ObjectUtil.equal(leads.getLeadsUserId(),newLeadsUserId)){
                    if ((!UserUtil.getUserId().equals(leads.getLeadsUserId())) && (leads.getLeadsUserId() != null)) {
                        addMessage(leads.getCustomerName(), leadsUserName, leads.getLeadsUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), leads.getLeadsId());
                    }

                    if ((!UserUtil.getUserId().equals(newLeadsUserId)) && newLeadsUserId != null) {
                        addMessage(leads.getCustomerName(), leadsUserName, newLeadsUserId, AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), leads.getLeadsId());
                    }
                }
            }

        }
    }

    @Autowired
    private CrmLeadsMapper crmLeadsMapper;

    @Override
    public void transfer(CrmLeadsTransferCustomer crmLeadsTransferCustomer) {

        List<CrmLeadsVO> crmLeadsVOS = crmLeadsMapper.selectCrmLeadsCount(crmLeadsTransferCustomer.getLeadsIds());

        List<Integer> customerIds = new ArrayList<>();
        Map<Integer, CrmModelSaveBO> crmModelSaveBoMap = new HashMap<>(8);

        boolean isTransfer = false;
        //判断线索是否转化，若已转化则返回
        for (Integer leadsId : crmLeadsTransferCustomer.getLeadsIds()) {
            CrmLeads leads = baseMapper.queryLeadsDataByLeadsId(leadsId);
            if (leads.getIsTransform() == 1) {
                isTransfer = true;
            }
            break;
        }

        if (isTransfer) {
            throw new CrmException(CrmCodeEnum.CRM_LEADS_TRANSFER_ERROR);
        }

        for (Integer leadsId : crmLeadsTransferCustomer.getLeadsIds()) {
            SpringUtils.getBean(ICrmLeadsService.class).transferCustomerData(leadsId, crmLeadsTransferCustomer, customerIds, crmModelSaveBoMap);
        }

        elasticsearchRestTemplate.refresh(getIndex());
    }

    /**
     * 保存客户信息
     *
     * @param leadsId
     * @param crmLeadsTransferCustomer
     * @param customerIds
     * @param crmModelSaveBoMap
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transferCustomerData(Integer leadsId, CrmLeadsTransferCustomer crmLeadsTransferCustomer, List<Integer> customerIds, Map<Integer, CrmModelSaveBO> crmModelSaveBoMap) {
        CrmModel leadsMap = queryByIdToTransfer(leadsId);
        CrmLeads crmLeads = BeanUtil.copyProperties(leadsMap, CrmLeads.class);

        //设置锁
        String redisKey = crmLeads.getSerialNumber();
        String redisValue = UUID.randomUUID().toString();
        Boolean result = redis.lock(redisKey, redisValue, 3, TimeUnit.SECONDS);
        if (!result) {
            throw new CrmException(CrmCodeEnum.BUSINESS_LOCK_DATA);
        }

        try {

            CrmCustomer customer = crmCustomerService.queryCustomerBySerialNumber(crmLeads.getSerialNumber());

            if (BeanUtil.isNotEmpty(customer)) {
                redis.unlock(redisKey, redisValue);
                throw new CrmException(CrmCodeEnum.CRM_LEADS_TRANSFER_FAIL);
//                return;
            }

            CrmCustomer crmCustomer = new CrmCustomer();
            crmCustomer.setLevel("C（非优先客户）");
            crmCustomer.setCustomerName(crmLeads.getCustomerName());
            crmCustomer.setSerialNumber(crmLeads.getSerialNumber());
            crmCustomer.setCourseSource(crmLeads.getCourseSource());
            crmCustomer.setNextTime(crmLeads.getNextTime());
            crmCustomer.setMobile(crmLeads.getMobile());
            crmCustomer.setTelephone(crmLeads.getTelephone());
            crmCustomer.setWechat(crmLeads.getWechat());
            crmCustomer.setCreateUserId(UserUtil.getUserId());
            crmCustomer.setOwnerUserId(crmLeads.getOwnerUserId());
            crmCustomer.setLeadsUserId(crmLeads.getLeadsUserId());
            crmCustomer.setCreateTime(new Date());
            crmCustomer.setUpdateTime(new Date());
            crmCustomer.setReceiveTime(new Date());
            crmCustomer.setDrawTime(new Date());
            crmCustomer.setRoUserId(",");
            crmCustomer.setRwUserId(",");
            crmCustomer.setDetailAddress(crmLeads.getAddress());
            crmCustomer.setLocation("");
            crmCustomer.setAddress("");
            crmCustomer.setLng("");
            crmCustomer.setLat("");
            crmCustomer.setRemark("");
            crmCustomer.setVipDealStatus("未成交");
            crmCustomer.setEmail(crmLeads.getEmail());
            crmCustomer.setStatus(1);
            crmCustomer.setLastContent(crmLeads.getLastContent());
            crmCustomer.setLastTime(crmLeads.getLastTime());
            //微信昵称
            crmCustomer.setWechatName(crmLeads.getLeadsName());
            //是否重复
            crmCustomer.setIsRepetition(crmLeads.getIsRepetition());
            //客户来源
            crmCustomer.setSource(crmLeads.getSource());

            crmCustomer.setOwnerDeptId(String.valueOf(UserCacheUtil.getUserInfo(crmLeads.getOwnerUserId()).getDeptId()));

            String customerBatchId = IdUtil.simpleUUID();
            crmCustomer.setBatchId(customerBatchId);
            if (null != crmLeads.getCreateUserId()) {
                crmCustomer.setLeadsCreateId(crmLeads.getCreateUserId());
            }
            if (null != crmLeads.getCreateTime()) {
                crmCustomer.setLeadsCreateTime(crmLeads.getCreateTime());
            }
            //是否加微信
            if (StringUtils.isNotBlank(String.valueOf(crmLeads.getAddWechat()))) {
                crmCustomer.setAddWechat(String.valueOf(crmLeads.getAddWechat()));
            }
            //加微信时间
            if (null != crmLeads.getAddWechatTime()) {
                crmCustomer.setAddWechatTime(crmLeads.getAddWechatTime());
            }
            if(null != crmLeads.getLeadsCreateTime()){
                crmCustomer.setLeadsFormTime(crmLeads.getLeadsCreateTime());
            }
            //是否报课
            if (StringUtils.isNotBlank(String.valueOf(crmLeads.getSignClass()))) {
                crmCustomer.setSignClass(String.valueOf(crmLeads.getSignClass()));
            }
            //报课时间
            if (null != crmLeads.getSignClassTime()) {
                crmCustomer.setSignClassTime(crmLeads.getSignClassTime());
            }

            List<CrmField> leadsFields = crmFieldService.list(CrmEnum.LEADS.getType(), false);
            List<CrmField> customerFields = crmFieldService.list(CrmEnum.CUSTOMER.getType(), true);
            List<CrmCustomerData> customerDataList = new ArrayList<>();
            Map<String, Object> customerExtraMap = new HashMap<>();
            for (CrmField leadsField : leadsFields) {
                for (CrmField customerField : customerFields) {
                    if (leadsField.getRelevant() != null && customerField.getFieldId().equals(leadsField.getRelevant())) {
                        if (customerField.getFieldType().equals(1)) {
                            customerExtraMap.put(customerField.getFieldName(), leadsMap.get(StrUtil.toCamelCase(leadsField.getFieldName())));
                        } else {
                            CrmCustomerData crmCustomerData = new CrmCustomerData();
                            crmCustomerData.setValue((String) leadsMap.get(StrUtil.toCamelCase(leadsField.getFieldName())));
                            crmCustomerData.setFieldId(customerField.getFieldId());
                            crmCustomerData.setName(customerField.getName());
                            crmCustomerData.setFieldName(StrUtil.toCamelCase(customerField.getFieldName()));
                            customerDataList.add(crmCustomerData);
                        }
                    }

                }
            }
            BeanUtil.fillBeanWithMap(customerExtraMap, crmCustomer, true);
            crmCustomer.setBatchId(customerBatchId);
            for (CrmField customerField : customerFields) {
                Integer isUnique = customerField.getIsUnique();
                String name = customerField.getName();
                Map<String, Object> customerMap = BeanUtil.beanToMap(crmCustomer);
                //当是否重复为否时判断数据的一致性
                if (BeanUtil.isEmpty(crmCustomer.getIsRepetition())) {
                    for (String key : customerMap.keySet()) {
                        if (key.equals(StrUtil.toCamelCase(customerField.getFieldName()))) {
                            Object value = customerMap.get(key);
                            if (value != null && !"".equals(value.toString())) {
                                if (isUnique == 1 && crmFieldService.queryCustomerFieldDuplicateByFixed(customerField.getFieldName(), value) > 0) {
                                    throw new CrmException(CrmCodeEnum.CRM_FIELD_EXISTED, name);
                                }
                            }
                        }
                    }
                }
            }

            //营销讲师的添加
            Result trainingResult = crmTrainingService.queryTrainingStatus();
            boolean trainingStatus = false;
            if(trainingResult.hasSuccess()){
                if(ObjectUtil.equal(trainingResult.getData(),1)){
                    trainingStatus = true;
                }
            }

            if(trainingStatus){
                if(StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTeacher())){
                    crmCustomer.setTeacherId(Long.valueOf(crmLeadsTransferCustomer.getTeacher()));
                }
                //训练营期数
                if (StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTrainingPeriods())) {
                    crmCustomer.setTrainingPeriods(crmLeadsTransferCustomer.getTrainingPeriods());
                } else {
                    crmCustomer.setTrainingPeriods(crmLeads.getTrainingPeriods());
                }
            }

            if (!crmCustomerSettingService.queryCustomerSettingNum(1, crmCustomer.getOwnerUserId())) {
                throw new CrmException(CrmCodeEnum.THE_NUMBER_OF_CUSTOMERS_HAS_REACHED_THE_LIMIT);
            }
            crmCustomerService.save(crmCustomer);
            Integer customerId = crmCustomer.getCustomerId();
            customerIds.add(customerId);
            //保存自定义字段
            saveCustomerField(customerDataList, customerBatchId);
            CrmModelSaveBO crmModelSaveBO = new CrmModelSaveBO();
            crmModelSaveBO.setEntity(BeanUtil.beanToMap(crmCustomer));
            List<CrmModelFiledVO> collect = customerDataList.stream().map(field -> BeanUtil.copyProperties(field, CrmModelFiledVO.class)).collect(Collectors.toList());
            crmModelSaveBO.setField(collect);
            crmModelSaveBoMap.put(customerId, crmModelSaveBO);

            if(trainingStatus){
                if(StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTeacher())){
                    actionRecordUtil.addConversionCustomerRecordV2(crmCustomer.getCustomerId(), CrmEnum.CUSTOMER, crmCustomer.getCustomerName(), crmCustomer.getTrainingPeriods(), UserCacheUtil.getUserName(Long.valueOf(crmLeadsTransferCustomer.getTeacher())));
                }else{
                    actionRecordUtil.addConversionCustomerRecordV2(crmCustomer.getCustomerId(), CrmEnum.CUSTOMER, crmCustomer.getCustomerName(), crmCustomer.getTrainingPeriods(), "");
                }
            }else{
                actionRecordUtil.addConversionCustomerRecord(crmCustomer.getCustomerId(),CrmEnum.CUSTOMER,crmCustomer.getCustomerName());
            }
            if(trainingStatus){
                String trainingPeriods = "";
                if (StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTrainingPeriods())) {
                    trainingPeriods = crmLeadsTransferCustomer.getTrainingPeriods();
                } else {
                    trainingPeriods = crmLeads.getTrainingPeriods();
                }
                if(StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTeacher())){
                    lambdaUpdate().set(CrmLeads::getIsTransform, 1).set(CrmLeads::getUpdateTime, new Date()).set(CrmLeads::getCustomerId, crmCustomer.getCustomerId()).set(CrmLeads::getTrainingPeriods, trainingPeriods).set(CrmLeads::getTeacherId, Long.valueOf(crmLeadsTransferCustomer.getTeacher()))
                            .eq(CrmLeads::getLeadsId, leadsId).update();
                }else{
                    lambdaUpdate().set(CrmLeads::getIsTransform, 1).set(CrmLeads::getUpdateTime, new Date()).set(CrmLeads::getCustomerId, crmCustomer.getCustomerId()).set(CrmLeads::getTrainingPeriods, trainingPeriods)
                            .eq(CrmLeads::getLeadsId, leadsId).update();
                }
            }else{
                lambdaUpdate().set(CrmLeads::getIsTransform, 1).set(CrmLeads::getUpdateTime, new Date()).set(CrmLeads::getCustomerId, crmCustomer.getCustomerId())
                        .eq(CrmLeads::getLeadsId, leadsId).update();
            }

            //转移操作记录
            List<CrmActionRecord> crmActionRecordList = crmActionRecordService.lambdaQuery().eq(CrmActionRecord::getActionId, leadsId).eq(CrmActionRecord::getTypes, 1).list();
            crmActionRecordList.forEach(crmActionRecord -> {
                crmActionRecord.setId(null);
                crmActionRecord.setTypes(CrmEnum.CUSTOMER.getType());
                crmActionRecord.setActionId(crmCustomer.getCustomerId());
            });
            crmActionRecordService.saveBatch(crmActionRecordList, 500);

            //转移活动数据
            List<CrmActivity> crmActivityList = crmActivityService.lambdaQuery().eq(CrmActivity::getActivityType, 1).eq(CrmActivity::getType, 1).eq(CrmActivity::getActivityTypeId, leadsId).list();
            List<String> adminFileIdList = new ArrayList<>();
            if (crmActivityList.size() != 0) {
                crmActivityList.forEach(crmActivity -> {
                    List<FileEntity> leadsRecordFiles = adminFileService.queryFileList(crmActivity.getBatchId());
                    String customerRecordBatchId = IdUtil.simpleUUID();
                    List<String> fileIds = leadsRecordFiles.stream().map(FileEntity::getFileId).collect(Collectors.toList());
                    crmActivity.setBatchId(customerRecordBatchId);
                    crmActivity.setActivityId(null);
                    crmActivity.setActivityType(CrmEnum.CUSTOMER.getType());
                    crmActivity.setActivityTypeId(crmCustomer.getCustomerId());
                    if(CollectionUtil.isNotEmpty(fileIds)){
                        adminFileService.saveBatchFileEntity(fileIds, customerRecordBatchId);
                    }
                });
                crmActivityService.saveBatch(crmActivityList, 100);
            }
            List<FileEntity> fileList = adminFileService.queryFileList(crmLeads.getBatchId());
            if (fileList.size() != 0) {
                fileList.forEach(adminFile -> {
                    adminFileIdList.add(adminFile.getFileId());
                });
                adminFileService.saveBatchFileEntity(adminFileIdList, customerBatchId);
            }

//            Integer customerId = customerIds.get(i);
            UpdateRequest updateRequest = new UpdateRequest(CrmEnum.LEADS.getIndex(), "_doc", leadsId.toString());
            CrmLeads crmLeads1 = baseMapper.queryLeadsDataByLeadsId(leadsId);
            Map<String, Object> map = new HashMap<>();
            map.put("isTransform", 1);
            map.put("updateTime", DateUtil.formatDateTime(new Date()));
            map.put("customerId", customerId);
            if(trainingStatus){
                if (StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTrainingPeriods())) {
                    map.put("trainingPeriods", crmLeadsTransferCustomer.getTrainingPeriods());
                } else {
                    map.put("trainingPeriods", crmLeads1.getTrainingPeriods());
                }

                if(StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTeacher())){
                    map.put("teacherId", crmLeadsTransferCustomer.getTeacher());
                    map.put("teacherName", UserCacheUtil.getUserName(Long.valueOf(crmLeadsTransferCustomer.getTeacher())));
                }
            }

            updateRequest.doc(map);
            try {
                elasticsearchRestTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                log.error("es 更新异常!");
            }
            customerService.savePage(crmModelSaveBoMap.get(customerId), customerId, false);

            if(trainingStatus){
                //营销讲师及训练营期数记录日志
                CrmLeads oldLeads = new CrmLeads();
                oldLeads.setTrainingPeriods(crmLeads.getTrainingPeriods());
                oldLeads.setTeacherId(crmLeads.getTeacherId());
                CrmLeads newLeads = new CrmLeads();
                newLeads.setTrainingPeriods(crmLeadsTransferCustomer.getTrainingPeriods());
                if(StringUtils.isNotEmpty(crmLeadsTransferCustomer.getTeacher())){
                    newLeads.setTeacherId(Long.valueOf(crmLeadsTransferCustomer.getTeacher()));
                }
                actionRecordUtil.updateRecord(BeanUtil.beanToMap(oldLeads), BeanUtil.beanToMap(newLeads), CrmEnum.LEADS, crmLeads.getLeadsName(), crmLeads.getLeadsId());

                // 讲师变更发送消息
                if (!ObjectUtil.equal(oldLeads.getTeacherId(), newLeads.getTeacherId())) {
                    String teacherName = UserCacheUtil.getUserName(newLeads.getTeacherId());

                    if (oldLeads.getTeacherId() != null) {
                        addMessage(crmLeads.getCustomerName(), teacherName, oldLeads.getTeacherId(), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                    }

                    if (newLeads.getTeacherId() != null) {
                        addMessage(crmLeads.getCustomerName(), teacherName, newLeads.getTeacherId(), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                    }
                }
            }


        } catch (CrmException e) {
            log.error("线索转化失败：" + e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(CrmCodeEnum.CRM_LEADS_TRANSFER_FAIL.getMsg());
        } finally {
            redis.unlock(redisKey, redisValue);
        }
    }


    private void saveCustomerField(List<CrmCustomerData> customerDataList, String batchId) {
        if (CollUtil.isEmpty(customerDataList) || StrUtil.isEmpty(batchId)) {
            return;
        }
        crmCustomerDataService.lambdaUpdate().eq(CrmCustomerData::getBatchId, batchId)
                .remove();
        customerDataList.forEach(fieldv -> {
            fieldv.setId(null);
            fieldv.setName(fieldv.getFieldName());
            fieldv.setCreateTime(DateUtil.date());
            fieldv.setBatchId(batchId);
            crmCustomerDataService.save(fieldv);
        });
    }


    /**
     * 下载导入模板
     *
     * @param response 线索id
     */
    @Override
    public void downloadExcel(HttpServletResponse response) throws IOException {
        List<CrmModelFiledVO> crmModelFiledList = queryField(null);
        crmModelFiledList.removeIf(model -> Arrays.asList(FieldEnum.FILE, FieldEnum.CHECKBOX, FieldEnum.USER, FieldEnum.STRUCTURE, FieldEnum.SINGLE_USER).contains(FieldEnum.parse(model.getType())));
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("线索导入表");
        sheet.setDefaultRowHeight((short) 400);
        CellStyle textStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        textStyle.setDataFormat(format.getFormat("@"));
        for (int i = 0; i < crmModelFiledList.size(); i++) {
            CrmModelFiledVO crmModel = crmModelFiledList.get(i);
//            if (FieldEnum.DATE.getType().equals(crmModel.getType())) {
//                CellStyle dateStyle = wb.createCellStyle();
//                DataFormat dateFormat = wb.createDataFormat();
//                dateStyle.setDataFormat(dateFormat.getFormat(DatePattern.NORM_DATE_PATTERN));
//                sheet.setDefaultColumnStyle(i, dateStyle);
//            } else {
//                sheet.setDefaultColumnStyle(i, textStyle);
//            }
            sheet.setDefaultColumnStyle(i, textStyle);
            sheet.setColumnWidth(i, 20 * 256);
        }
        CellStyle cellStyle = wb.createCellStyle();
        HSSFRow titleRow = sheet.createRow(0);
        cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = wb.createFont();
        font.setBold(true);
        font.setFontHeightInPoints((short) 16);
        cellStyle.setFont(font);
        titleRow.createCell(0).setCellValue("线索导入模板(*)为必填项");
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        titleRow.getCell(0).setCellStyle(cellStyle);
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, crmModelFiledList.size() - 1);
        sheet.addMergedRegion(region);
        try {
            HSSFRow row = sheet.createRow(1);
            for (int i = 0; i < crmModelFiledList.size(); i++) {
                CrmModelFiledVO crmModel = crmModelFiledList.get(i);
                //TODO 线索导入判断 是否加微信 必填判断
                if ("add_wechat".equals(crmModel.getFieldName())) {
                    crmModel.setIsNull(0);
                }
                List<String> setting = crmModel.getSetting().stream().map(Object::toString).collect(Collectors.toList());
                // 在第一行第一个单元格，插入选项
                HSSFCell cell = row.createCell(i);
                // 普通写入操作
                String cellValue = crmModel.getName() + (crmModel.getIsNull() == 1 ? "(*)" : "");
                if (FieldEnum.LEVEL_LINKAGE.getType().equals(crmModel.getType())) {
                    cellValue = cellValue + "(每级之间请用“|”分割)";
                }
                cell.setCellValue(cellValue);

                if (setting.size() != 0) {
                    String fieldName = "_" + crmModel.getFieldName();
                    HSSFSheet hidden = wb.createSheet(fieldName);
                    HSSFCell sheetCell;
                    for (int j = 0, length = setting.size(); j < length; j++) {
                        String name = setting.get(j);
                        HSSFRow sheetRow = hidden.createRow(j);
                        sheetCell = sheetRow.createCell(0);
                        sheetCell.setCellValue(name);
                    }
                    Name namedCell = wb.createName();
                    namedCell.setNameName(fieldName);
                    namedCell.setRefersToFormula(fieldName + "!$A$1:$A$" + setting.size());
                    CellRangeAddressList regions = new CellRangeAddressList(2, Integer.MAX_VALUE, i, i);
                    DVConstraint constraint = DVConstraint.createFormulaListConstraint(fieldName);
                    HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
                    wb.setSheetHidden(wb.getSheetIndex(hidden), true);
                    sheet.addValidationData(dataValidation);
                }
            }
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=leads_import.xls");
            wb.write(response.getOutputStream());
        } catch (IOException e) {
            log.error("获取导入模板异常", e);
        } finally {
            wb.close();
        }
    }

    /**
     * 导出
     *
     * @param response resp
     * @param search   搜索对象
     */
    @Override
    public void exportExcel(HttpServletResponse response, CrmSearchBO search) {
        List<Map<String, Object>> dataList = queryPageList(search).getList();
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = crmFieldService.queryListHead(getLabel().getType());
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "线索信息");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
            dataList.forEach(record -> {
                record.put("isTransform", Objects.equals(1, record.get("isTransform")) ? "是" : "否");
            });
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 30);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            String fileName = "线索" + DateUtils.dateTimeNow() + ".xls";
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);

            // 新增消息
            addMessage(dataList.size() <= 0 ? "0" : String.valueOf(dataList.size()), "导出数据" + String.valueOf(dataList.size()) + "条", UserUtil.getUserId(), AdminMessageEnum.CRM_LEADS_EXPORT.getType(), null);

        } catch (Exception e) {
            log.error("导出线索错误：", e);
        }
    }

    /**
     * 标星
     *
     * @param leads 线索id
     */
    @Override
    public void star(Integer leads) {
        LambdaQueryWrapper<CrmLeadsUserStar> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrmLeadsUserStar::getLeadsId, leads);
        wrapper.eq(CrmLeadsUserStar::getUserId, UserUtil.getUserId());
        CrmLeadsUserStar star = crmLeadsUserStarService.getOne(wrapper);
        if (star == null) {
            star = new CrmLeadsUserStar();
            star.setLeadsId(leads);
            star.setUserId(UserUtil.getUserId());
            crmLeadsUserStarService.save(star);
        } else {
            crmLeadsUserStarService.removeById(star.getId());
        }
    }

    @Override
    public List<CrmModelFiledVO> information(Integer leadsId) {
        //将主表和子表数据查询为一个map
        //字段类型 1不可编辑不可查看 2可查看不可编辑 3可编辑可查看
        //将map 中 字段类型 小于等于1 的key  remove掉
        CrmModel crmModel = queryById(leadsId);
        Set<String> set = crmModel.keySet();
        List<String> keyList = new ArrayList<>(set);

        List<String> systemFieldList = Arrays.asList("serialNumber", "vipDealStatus", "vipDealTime", "isTransform", "createUserName", "createTime", "updateTime", "lastTime", "lastContent");
        List<CrmModelFiledVO> crmModelFiledVOS = queryInformation(crmModel, keyList);
        List<CrmModelFiledVO> filedVOS = crmModelFiledVOS.stream().sorted(Comparator.comparingInt(r -> -r.getFieldType())).peek(r -> {
            if (FieldEnum.SELECT.getType().equals(r.getType())) {
                if (CollUtil.isEmpty(r.getSetting())) {
                    r.setSetting(new ArrayList<>(StrUtil.splitTrim(r.getOptions(), Const.SEPARATOR)));
                }
            }
            if (systemFieldList.contains(r.getFieldName())) {
                r.setAuthLevel(2);
                r.setSysInformation(1);
            } else {
                r.setSysInformation(0);
            }
        }).collect(Collectors.toList());

        List<String> removeField = Arrays.asList("");
        filedVOS.removeIf(item -> removeField.contains(item.getFieldName()));

        return filedVOS;
    }

    /**
     * 查询文件数量
     *
     * @param leadsId id
     * @return data
     */
    @Override
    public CrmInfoNumVO num(Integer leadsId) {
        List<String> batchIdList = new ArrayList<>();
        CrmLeads crmLeads = getById(leadsId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmLeadsData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmLeadsData::getValue);
            wrapper.eq(CrmLeadsData::getBatchId, crmLeads.getBatchId());
            wrapper.in(CrmLeadsData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            batchIdList.addAll(crmLeadsDataService.listObjs(wrapper, Object::toString));
        }
        batchIdList.add(crmLeads.getBatchId());
        batchIdList.addAll(crmActivityService.queryFileBatchId(crmLeads.getLeadsId(), getLabel().getType()));
        CrmInfoNumVO numVO = new CrmInfoNumVO();
        numVO.setFileCount(fileService.queryNum(batchIdList));
        return numVO;
    }


    /**
     * 查询文件列表
     *
     * @param leadsId id
     * @return file
     */
    @Override
    public List<FileEntity> queryFileList(Integer leadsId) {
        List<FileEntity> fileEntityList = new ArrayList<>();
        CrmLeads crmLeads = getById(leadsId);
        AdminFileService fileService = SpringUtils.getBean(AdminFileService.class);
        fileService.queryFileList(crmLeads.getBatchId()).forEach(fileEntity -> {
            fileEntity.setSource("附件上传");
            fileEntity.setReadOnly(0);
            fileEntityList.add(fileEntity);
        });
        List<CrmField> crmFields = crmFieldService.queryFileField();
        if (crmFields.size() > 0) {
            LambdaQueryWrapper<CrmLeadsData> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(CrmLeadsData::getValue);
            wrapper.eq(CrmLeadsData::getBatchId, crmLeads.getBatchId());
            wrapper.in(CrmLeadsData::getFieldId, crmFields.stream().map(CrmField::getFieldId).collect(Collectors.toList()));
            List<FileEntity> data = fileService.queryFileList(crmLeadsDataService.listObjs(wrapper, Object::toString));
            data.forEach(fileEntity -> {
                fileEntity.setSource("线索详情");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        List<String> stringList = crmActivityService.queryFileBatchId(crmLeads.getLeadsId(), getLabel().getType());
        if (stringList.size() > 0) {
            List<FileEntity> data = fileService.queryFileList(stringList);
            data.forEach(fileEntity -> {
                fileEntity.setSource("跟进记录");
                fileEntity.setReadOnly(1);
                fileEntityList.add(fileEntity);
            });
        }
        return fileEntityList;
    }

    @Override
    public void updateInformation(CrmUpdateInformationBO updateInformationBO) {
        String batchId = updateInformationBO.getBatchId();
        Integer leadsId = updateInformationBO.getId();
        updateInformationBO.getList().forEach(record -> {
            CrmLeads oldLeads = getById(updateInformationBO.getId());
            if (UserUtil.getUser().getRoles().contains(UserUtil.getSuperRole())) {
            } else {
                if (oldLeads.getIsTransform() == 1) {
                    throw new CrmException(CrmCodeEnum.CRM_LEADS_EDIT_ISTRANSFER_ERROR);
                }
            }
            Map<String, Object> oldLeadsMap = BeanUtil.beanToMap(oldLeads);
            if (record.getInteger("fieldType") == 1) {
                Map<String, Object> crmLeadsMap = new HashMap<>(oldLeadsMap);
                crmLeadsMap.put(record.getString("fieldName"), record.get("value"));
                CrmLeads crmLeads = BeanUtil.mapToBean(crmLeadsMap, CrmLeads.class, true);
                //验证电话格式
                if (StringUtils.isNotBlank(crmLeads.getTelephone())) {
                    if (!(crmLeads.getTelephone().matches(Const.REG_EXP_MOBILE) || crmLeads.getTelephone().matches(Const.REG_EXP_TELEPHONE))) {
                        throw new CrmException(CrmCodeEnum.CRM_REG_EXP_ERROR);
                    }
                }
                if ("teacherId".equals(record.getString("fieldName"))) {
                    if(!ObjectUtil.equal(oldLeads.getTeacherId(),record.getLong("value"))){
                        String teacherName = UserCacheUtil.getUserName(record.getLong("value"));
                        if (!UserUtil.getUserId().equals(oldLeads.getTeacherId())) {
                            if (oldLeads.getTeacherId() != null) {
                                addMessage(oldLeads.getCustomerName(), teacherName, oldLeads.getTeacherId(), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                            }
                        }
                        if (record.getLong("value") != null) {
                            addMessage(oldLeads.getCustomerName(), teacherName, record.getLong("value"), AdminMessageEnum.CRM_LEADS_CHANGE_TEACHER_USER.getType(), crmLeads.getLeadsId());
                        }
                    }
                }
                // 销售负责人
                if ("ownerUserId".equals(record.getString("fieldName"))) {
                    if(!ObjectUtil.equal(oldLeads.getOwnerUserId(),record.getLong("value"))){
                        String ownerUserName = UserCacheUtil.getUserName(record.getLong("value"));
                        if (!UserUtil.getUserId().equals(oldLeads.getOwnerUserId())) {
                            if (oldLeads.getOwnerUserId() != null) {
                                addMessage(oldLeads.getCustomerName(), ownerUserName, oldLeads.getOwnerUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), crmLeads.getLeadsId());
                            }
                        }
                        if (record.getLong("value") != null) {
                            addMessage(oldLeads.getCustomerName(), ownerUserName, record.getLong("value"), AdminMessageEnum.CRM_LEADS_CHANGE_OWNER_USER.getType(), crmLeads.getLeadsId());
                        }
                    }
                }
                // 线索负责人
                if ("leadsUserId".equals(record.getString("fieldName"))) {
                    if(!ObjectUtil.equal(oldLeads.getLeadsUserId(),record.getLong("value"))){
                        String leadsUserName = UserCacheUtil.getUserName(record.getLong("value"));
                        if (!UserUtil.getUserId().equals(oldLeads.getLeadsUserId())) {
                            if (oldLeads.getLeadsUserId() != null) {
                                addMessage(oldLeads.getCustomerName(), leadsUserName, oldLeads.getLeadsUserId(), AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), crmLeads.getLeadsId());
                            }
                        }
                        if (record.getLong("value") != null) {
                            addMessage(oldLeads.getCustomerName(), leadsUserName, record.getLong("value"), AdminMessageEnum.CRM_LEADS_CHANGE_LEADS_USER.getType(), crmLeads.getLeadsId());
                        }
                    }
                }
                actionRecordUtil.updateRecord(oldLeadsMap, crmLeadsMap, CrmEnum.LEADS, crmLeads.getLeadsName(), crmLeads.getLeadsId());
                update().set(StrUtil.toUnderlineCase(record.getString("fieldName")), record.get("value")).eq("leads_id", updateInformationBO.getId()).update();
            } else if (record.getInteger("fieldType") == 0 || record.getInteger("fieldType") == 2) {

                CrmLeadsData leadsData = crmLeadsDataService.lambdaQuery().select(CrmLeadsData::getValue).eq(CrmLeadsData::getFieldId, record.getInteger("fieldId"))
                        .eq(CrmLeadsData::getBatchId, batchId).one();
                String value = leadsData != null ? leadsData.getValue() : null;
                boolean isUpdate = false;
                if ((null == value && null == record.get("value"))) {
                    isUpdate = false;
                } else if (null != value && !value.equals(String.valueOf(record.get("value")))) {
                    isUpdate = true;
                } else if (null != record.get("value") && !String.valueOf(record.get("value")).equals(value)) {
                    isUpdate = true;
                }
                if (isUpdate) {
                    String detail = actionRecordUtil.getDetailByFormTypeAndValue(record, value);
                    actionRecordUtil.publicContentRecord(CrmEnum.LEADS, BehaviorEnum.UPDATE, leadsId, oldLeads.getLeadsName(), detail);
                    boolean bol = crmLeadsDataService.lambdaUpdate()
                            .set(CrmLeadsData::getName, record.getString("fieldName"))
                            .set(CrmLeadsData::getValue, record.getString("value"))
                            .eq(CrmLeadsData::getFieldId, record.getInteger("fieldId"))
                            .eq(CrmLeadsData::getBatchId, batchId).update();
                    if (!bol) {
                        CrmLeadsData crmLeadsData = new CrmLeadsData();
                        crmLeadsData.setFieldId(record.getInteger("fieldId"));
                        crmLeadsData.setName(record.getString("fieldName"));
                        crmLeadsData.setValue(record.getString("value"));
                        crmLeadsData.setCreateTime(new Date());
                        crmLeadsData.setBatchId(batchId);
                        crmLeadsDataService.save(crmLeadsData);
                    }
                }
            }
            updateField(record, leadsId);
        });

    }

    @Override
    public List<String> eventLeads(CrmEventBO crmEventBO) {
        return getBaseMapper().eventLeads(crmEventBO);
    }

    @Override
    public BasePage<Map<String, Object>> eventLeadsPageList(QueryEventCrmPageBO eventCrmPageBO) {
        Long userId = eventCrmPageBO.getUserId();
        Long time = eventCrmPageBO.getTime();
        if (userId == null) {
            userId = UserUtil.getUserId();
        }
        List<Integer> leadsIds = getBaseMapper().eventLeadsList(userId, new Date(time));
        if (leadsIds.size() == 0) {
            return new BasePage<>();
        }
        List<String> collect = leadsIds.stream().map(Object::toString).collect(Collectors.toList());
        CrmSearchBO crmSearchBO = new CrmSearchBO();
        crmSearchBO.setSearchList(Collections.singletonList(new CrmSearchBO.Search("_id", "id", CrmSearchBO.FieldSearchEnum.ID, collect)));
        crmSearchBO.setLabel(CrmEnum.LEADS.getType());
        crmSearchBO.setPage(eventCrmPageBO.getPage());
        crmSearchBO.setLimit(eventCrmPageBO.getLimit());
        BasePage<Map<String, Object>> page = queryPageList(crmSearchBO);
        return page;
    }

    @Override
    public List<CrmDataCheckVO> dataCheck(CrmDataCheckBO dataCheckBO) {
        if (StringUtils.isBlank(dataCheckBO.getName()) && StringUtils.isBlank(dataCheckBO.getPhone())
                && StringUtils.isBlank(dataCheckBO.getQq()) && StringUtils.isBlank(dataCheckBO.getWechat())) {
            return new ArrayList<>();
        }
        List<CrmDataCheckVO> list = getBaseMapper().dataCheck(dataCheckBO);
        for (CrmDataCheckVO crmDataCheckVO : list) {
            if (crmDataCheckVO.getOwnerUserId() != null) {
                crmDataCheckVO.setOwnerUserName(UserCacheUtil.getUserName(crmDataCheckVO.getOwnerUserId()));
            }
            if (crmDataCheckVO.getCreateUserId() != null) {
                crmDataCheckVO.setCreateUserName(UserCacheUtil.getUserName(crmDataCheckVO.getCreateUserId()));
            }
        }
        return list;
    }


    /**
     * 有效表单数
     *
     * @return
     */
    @Override
    public Integer validDataNum(String laiyuan, String qishu) {
        Integer num = getBaseMapper().validDataNum(laiyuan, qishu);
        return null != num ? num : 0;
    }

    /**
     * 加客服数量
     *
     * @param laiyuan
     * @param qishu
     * @return
     */
    @Override
    public Integer addCustomerServiceNum(String laiyuan, String qishu) {
        Integer num = getBaseMapper().addCustomerServiceNum(laiyuan, qishu);
        return null != num ? num : 0;
    }

    /**
     * 小额报课数量
     *
     * @param laiyuan
     * @param qishu
     * @return
     */
    @Override
    public Integer addClassReportNum(String laiyuan, String qishu) {
        Integer num = getBaseMapper().addClassReportNum(laiyuan, qishu);
        return null != num ? num : 0;
    }

    @Override
    public CrmLeads queryLeadsDataBySerialNumber(String serialNumber) {
        return baseMapper.queryLeadsDataBySerialNumber(serialNumber);
    }

    public List<CrmLeads> queryLeadsList(String telephone) {
        return baseMapper.queryTelephoneUniqueList(telephone);
    }

    public List<CrmLeads> queryLeadsList1(String wechat) {
        return baseMapper.queryWechatUniqueList(wechat);
    }

    @Override
    public Integer queryLeadsWechatDataByData(String wechat) {
        return baseMapper.queryLeadsWechatDataByData(wechat);
    }

    @Override
    public Integer queryLeadsTelephoneDataByData(String wechat) {
        return baseMapper.queryLeadsTelephoneDataByData(wechat);
    }

    public List<CrmTmkLeads> queryTMKLeads(CrmRoiSearchBO search) {
        if (StringUtils.isNotBlank(search.getPutinPlatform())) {
            String[] allPutinfrom = search.getPutinPlatform().split(",");
            search.setPutinPlatforms(allPutinfrom);
        }
        List<CrmTmkLeads> tmkList = baseMapper.queryTmkLeads(search);
        DecimalFormat format = new DecimalFormat("0.00");
        //计算合计
        if (tmkList.size() > 0) {
            tmkList.get(0).setAllPutinSum((int) tmkList.stream().mapToDouble(CrmTmkLeads::getAllPutin).sum());
            tmkList.get(0).setClassNumSum((int) tmkList.stream().mapToDouble(CrmTmkLeads::getClassNum).sum());
            tmkList.get(0).setWeChatNumSum((int) tmkList.stream().mapToDouble(CrmTmkLeads::getWeChatNum).sum());
            tmkList.get(0).setPutinNumSum((int) tmkList.stream().mapToDouble(CrmTmkLeads::getPutinNum).sum());
            tmkList.get(0).setClassRateSum(Double.valueOf(format.format((float) tmkList.get(0).getClassNumSum() / (float) tmkList.get(0).getAllPutinSum() * 100)));
            tmkList.get(0).setWeChatRateSum(Double.valueOf(format.format((float) tmkList.get(0).getWeChatNumSum() / (float) tmkList.get(0).getAllPutinSum() * 100)));
            tmkList.get(0).setPutinOkRateSum(Double.valueOf(format.format((float) tmkList.get(0).getPutinNumSum() / (float) tmkList.get(0).getAllPutinSum() * 100)));
        }

        for (int i = 0; i < tmkList.size(); i++) {
            if (tmkList.get(i).getAllPutin() != null && tmkList.get(i).getAllPutin() != 0) {
                tmkList.get(i).setClassRate(Double.valueOf(format.format((float) tmkList.get(i).getClassNum() / (float) tmkList.get(i).getAllPutin() * 100)));
                tmkList.get(i).setWeChatRate(Double.valueOf(format.format((float) tmkList.get(i).getWeChatNum() / (float) tmkList.get(i).getAllPutin() * 100)));
                tmkList.get(i).setPutinOkRate(Double.valueOf(format.format((float) tmkList.get(i).getPutinNum() / (float) tmkList.get(i).getAllPutin() * 100)));
            }
            if (tmkList.get(i).getClassRate() == null) {
                tmkList.get(i).setClassRate(0.00);
            }
            if (tmkList.get(i).getPutinOkRate() == null) {
                tmkList.get(i).setPutinOkRate(0.00);
            }
            if (tmkList.get(i).getWeChatRate() == null) {
                tmkList.get(i).setWeChatRate(0.00);
            }
        }

        return tmkList;
    }

    public List<CrmFieldSortVO> queryTmkListHead() {
        List<CrmFieldSortVO> list = new ArrayList<>();
        list.add(new CrmFieldSortVO().setName("投放平台").setType(FieldEnum.SELECT.getType()).setFieldName("dataFrom").setFormType(FieldEnum.SELECT.getFormType()));
        list.add(new CrmFieldSortVO().setName("录入表单数量").setType(FieldEnum.NUMBER.getType()).setFieldName("allPutin").setFormType(FieldEnum.NUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("加微信表单数").setType(FieldEnum.NUMBER.getType()).setFieldName("weChatNum").setFormType(FieldEnum.NUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("加微信率(%)").setType(FieldEnum.FLOATNUMBER.getType()).setFieldName("weChatRate").setFormType(FieldEnum.FLOATNUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("报课表单数").setType(FieldEnum.NUMBER.getType()).setFieldName("classNum").setFormType(FieldEnum.NUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("报课率(%)").setType(FieldEnum.FLOATNUMBER.getType()).setFieldName("classRate").setFormType(FieldEnum.FLOATNUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("成交表单数").setType(FieldEnum.NUMBER.getType()).setFieldName("putinNum").setFormType(FieldEnum.NUMBER.getFormType()));
        list.add(new CrmFieldSortVO().setName("成交率(%)").setType(FieldEnum.FLOATNUMBER.getType()).setFieldName("putinOkRate").setFormType(FieldEnum.FLOATNUMBER.getFormType()));

        return list;
    }

    @Override
    public void tmkExportExcel(HttpServletResponse response, CrmRoiSearchBO search) {
        if (StringUtils.isNotBlank(search.getPutinPlatform())) {
            String allPutinPlatform = search.getPutinPlatform();
            search.setPutinPlatforms(allPutinPlatform.split(","));
        }
        List<CrmTmkLeads> crmPutinStatisticsList = queryTMKLeads(search);
        List<Map<String, Object>> dataList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(crmPutinStatisticsList)) {
            for (CrmTmkLeads crmTmkLeads : crmPutinStatisticsList) {
                Map<String, Object> map = new HashMap();
                map.put("dataFrom", crmTmkLeads.getDataFrom());
                map.put("category", crmTmkLeads.getCategory());
                map.put("allPutin", crmTmkLeads.getAllPutin());
                map.put("weChatNum", crmTmkLeads.getWeChatNum());
                map.put("weChatRate", crmTmkLeads.getWeChatRate());
                map.put("classNum", crmTmkLeads.getClassNum());
                map.put("classRate", crmTmkLeads.getWeChatRate());
                map.put("putinNum", crmTmkLeads.getPutinNum());
                map.put("putinOkRate", crmTmkLeads.getPutinOkRate());
                dataList.add(map);
            }
        }
        try (ExcelWriter writer = ExcelUtil.getWriter()) {
            List<CrmFieldSortVO> headList = queryTmkListHead();
            headList.forEach(head -> writer.addHeaderAlias(head.getFieldName(), head.getName()));
            writer.merge(headList.size() - 1, "投放渠道数据展示");
            if (dataList.size() == 0) {
                Map<String, Object> record = new HashMap<>();
                headList.forEach(head -> record.put(head.getFieldName(), ""));
                dataList.add(record);
            }
            writer.setOnlyAlias(true);
            writer.write(dataList, true);
            writer.setRowHeight(0, 30);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=roi_putin_monery.xls");
            ServletOutputStream out = response.getOutputStream();

            writer.flush(out);
        } catch (Exception e) {
            log.error("导出投放渠道数据展示错误：", e);
        }
    }

    @Autowired
    private CrmCustomerMapper crmCustomerMapper;

    //撤销转化
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void revokeTransfer(CrmLeadsTransferCustomer crmLeadsTransferCustomer) {
        List<CrmLeadsVO> crmLeadsVOS = crmLeadsMapper.selectCrmLeadsByList(crmLeadsTransferCustomer.getLeadsIds());
        for (CrmLeadsVO crmLeadsVO : crmLeadsVOS) {
            Integer customerId = crmLeadsVO.getCustomerId();
            CrmCustomer customer = crmCustomerMapper.queryByIdStatus(customerId);
            if (customer == null) {
                crmLeadsMapper.updateTransform(crmLeadsVO.getLeadsId());
                actionRecordUtil.revokeLeadsRecord(crmLeadsVO.getLeadsId(), CrmEnum.LEADS, crmLeadsVO.getLeadsName());
            } else {
                throw new CrmException(CrmCodeEnum.CRM_LEADS_REVOKETRANSFER_ERROR);
            }
        }
        for (Integer leadsId : crmLeadsTransferCustomer.getLeadsIds()) {
            UpdateRequest updateRequest = new UpdateRequest(CrmEnum.LEADS.getIndex(), "_doc", leadsId.toString());
            Map<String, Object> map = new HashMap<>();
            map.put("isTransform", 0);
            map.put("updateTime", DateUtil.formatDateTime(new Date()));
            map.put("customerId", 0);
            updateRequest.doc(map);
            try {
                elasticsearchRestTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                log.error("es 更新异常!");
            }
        }

        elasticsearchRestTemplate.refresh(getIndex());

    }

    public Map<String,Object> queryLeadsFieldForTraining(){
        QueryWrapper<CrmField> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("label", 1);
        queryWrapper.in("field_name", "training_periods","teacher_id");
        List<CrmField> fieldList = crmFieldService.getBaseMapper().selectList(queryWrapper);
        Map<String,Object> dataMap = new HashMap<>();
        for (CrmField field : fieldList){
            dataMap.put(StringUtils.toCamelCase(field.getFieldName()) + "ForNotNull",field.getIsNull());
        }
        return dataMap;
    }

    public List<Map<String, Long>> queryAllLeadsStatis(String startDate, String endDate){
        return baseMapper.queryAllLeadsStatis(startDate, endDate);
    }

    public Integer queryLeadsStatisForSource(CrmRoiPutinPageBO data){
        return baseMapper.queryLeadsStatisForSource(data);
    }

    public List<CrmLeadsRoiStatisVO> queryLeadsAndCustomerStatisForData(String putinPlatform,String startDate, String endDate){
        return baseMapper.queryLeadsAndCustomerStatisForData(putinPlatform, startDate, endDate);
    }

    public List<CrmLeadsRoiStatisVO> queryLeadsStatisForData(String putinPlatform,String startDate, String endDate,List<Long> userIdList){
        return baseMapper.queryLeadsStatisForData(putinPlatform, startDate, endDate,userIdList);
    }

    public List<CrmLeadsRoiStatisVO> queryRoiStatis(String startDate, String endDate){
        return baseMapper.queryRoiStatis(startDate, endDate);
    }

}
